const Client = require('ssh2-sftp-client')
const glob = require('glob')
const fs = require('fs')
const sftp = new Client()

module.exports = class UploadPlugin {
    constructor({
        enabled = false,
        host='127.0.0.1',
        username='root',
        password='',
        port = '6222',
        serverPath = '/',
        filterFile = null
    }){
        this.enabled = enabled;
        this.serverPath = serverPath;
        this.distPath = '';
        this.filterFile = filterFile;
        this.config = {
              host, // 服务器地址
              port,
              username,
              password
        }
    }
    apply(compiler) {
       
       // tapPromise 通过promise的方式调用
       compiler.hooks.afterEmit.tapPromise("tapPromise", (compilation)=>{
            return new Promise((resolve,reject)=>{
                if(this.enabled){
                    //获取需要上传的文件目录
                    this.distPath = compilation.outputOptions.path.replace(/\\/g,'/')+"/";
                    console.log("需要上传的文件目录:"+this.distPath);
                    console.log("****开始上传文件到开发环境****");

                    sftp.connect(this.config).then(() => { // 连接服务器

                          sftp.list(this.serverPath).then(list => {
                            // console.log(list);
                            this.deleteServerFile(list).then(() => {
                            //文件删除成功
                              this.globLocalFile()
                                console.log('文件删除成功');
                                resolve();
                            })
                          }).catch(err => {
                            this.fexError(err)
                            resolve();
                          })
                    }).catch(err => {
                        this.fexError('sftp连接失败' + err);
                        resolve();
                    })
                }
                else
                {
                    resolve()
                }
            })
       })
    }
    async deleteServerFile(list) { // 删除服务器上文件(夹)
       for (const fileInfo of list) {
          const path = this.serverPath + fileInfo.name
          if (fileInfo.type === '-') {
            await sftp.delete(path)
          } else {
            await sftp.rmdir(path, true)
          }
       }
       return new Promise(resovle => {
          resovle()
       })
    }
    globLocalFile() { // 获取本地路径所有文件
        glob(this.distPath + '**', (er, files) => { // 本地目录下所有文件(夹)的路径
          files.splice(0, 1) // 删除路径../dist/
          if (this.filterFile && typeof this.filterFile === 'function') files = files.filter(x => this.filterFile(x))
          this.uploadFileToSftp(files)
        })
    }
    async uploadFileToSftp(files) { // 传输文件到服务器
        for (let localSrc of files) {
            
            let targetSrc = localSrc.replace(this.distPath, this.serverPath);
          
            if(targetSrc){
                if (fs.lstatSync(localSrc).isDirectory()) { // 是文件夹
                    await sftp.mkdir(targetSrc)
                  } else {
                    await sftp.put(localSrc, targetSrc)
                  }
            }
          
        }
        console.log('文件已上传至开发服务器!')
        sftp.end()
    }
    fexError(err) { // 出错请调用此方法
        sftp.end()
        console.error('sftpError:', err)
    }
};